package wc

import (
	"errors"
	"github.com/boltdb/bolt"
	"github.com/silenceper/wechat/server"
	"github.com/silenceper/wechat/user"
	"log"
	"main/session"
	"time"
)

const (
	NoneMode      = "none"
	LoveMode      = "love"
	BookMode      = "book"
	BindGrade     = "grade"
	PreLoveMode   = "pre_love"
	ResourcesMode = "resources"
)

var (
	UserNotExistsError = errors.New("user not exists")
	UserMarshalFail    = errors.New("user marshal fail")
)

type UserInfo struct {
	Mode            string                 `json:"mode"`
	OpenID          string                 `json:"open_id"`
	InfoDetail      *user.Info             `json:"info_detail" `
	CTX             map[string]interface{} `json:"ctx"`
	LastMessageTime int64                  `json:"last_message_time"`
}

func (u *UserInfo) SetCTX(key string, value interface{}) error {
	if u == nil {
		return errors.New("empty pointer")
	}
	if u.CTX == nil {
		u.CTX = make(map[string]interface{}, 4)
	}
	u.CTX[key] = value
	u.SaveUser()
	return nil
}
func (u *UserInfo) GetCTX(key string) (interface{}, error) {
	if u == nil {
		return nil, errors.New("empty pointer")
	}

	if u.CTX == nil {
		u.CTX = make(map[string]interface{}, 8)
		return nil, errors.New("ctx empty")
	}

	if k, exists := u.CTX[key]; exists {
		return k, nil
	} else {
		return "", errors.New("key not exists")
	}
}
func (u *UserInfo) UpdateTime() {
	u.LastMessageTime = time.Now().Unix()
}

func GetUser(svr *server.Server) UserInfo {

	oid := svr.GetOpenID()
	// 查看是否存在于Hub中
	var res UserInfo
	// 从bolt中获取
	if err := session.GetDb().View(func(tx *bolt.Tx) error {
		b := tx.Bucket(session.DBUser)
		if b != nil {
			data := b.Get([]byte(oid))
			// 如果用户数据不存在
			if data == nil {
				return UserNotExistsError
			}
			err := res.UnmarshalJSON(data)
			// 反序列化错误
			if err != nil {
				return UserMarshalFail
			}

			if res.OpenID == "" {
				return UserNotExistsError
			}

		} else {
			panic("bucket not exist")
		}
		return nil
	}); err != nil {
		// 构建一个新的用户
		res := UserInfo{
			Mode:            NoneMode,
			OpenID:          oid,
			InfoDetail:      &user.Info{},
			CTX:             make(map[string]interface{}, 4), // 每个人预留五个空间应该足够了
			LastMessageTime: time.Now().Unix(),
		}

		// 获取真实用户信息
		if uinfo, err := getUserinfo(svr); err != nil {
			log.Println(err.Error())
			return res
		} else {
			res.InfoDetail = uinfo
			// 函数返回之后把这个用户的信息存起来
		}
		defer res.SaveUser()
		return res
	} else {

		// 说明这个用户没有详细用户数据数据
		if res.InfoDetail.OpenID == "" {
			uinfo, err := getUserinfo(svr)
			if err != nil {
				log.Println(err.Error())
				return res
			} else {
				res.InfoDetail = uinfo

				defer res.SaveUser()
				return res
			}
		}

		return res
	}
}

func getUserinfo(svr *server.Server) (userInfo *user.Info, err error) {
	return user.NewUser(svr.Context).GetUserInfo(svr.GetOpenID())
}

func (u UserInfo) SaveUser() {
	_ = session.GetDb().Update(func(tx *bolt.Tx) error {
		// 选择桶
		b := tx.Bucket(session.DBUser)
		if b != nil {
			// 序列化
			ub, err := u.MarshalJSON()
			if err == nil {
				// 存储
				_ = b.Put([]byte(u.OpenID), ub)
			}
		}
		return nil
	})
}

func (u *UserInfo) SetMode(key string) {
	u.Mode = key
	// 存起来，更新
	u.SaveUser()
}
